package com.ews.onlineexchange.util;
import com.ews.onlineexchange.exception.ValidationException;
import org.apache.commons.collections4.BidiMap;
import org.apache.commons.collections4.bidimap.TreeBidiMap;
import java.io.Serializable;
import java.util.*;
import java.util.regex.Pattern;

public class SerialnumberUtil implements Serializable {

    /**
     *
     */
    private static final long serialVersionUID = 1L;

    private static final String NUMBER_REG = "^[a-z0-9A-Z]+$\\";

    /**
     * 工商注册号验证
     * @param gszc
     * @return
     */
    public static boolean isRightGszc(String gszc) {
        if (null == gszc) return false;
        if (gszc.length() != 15 ) return false;
        return gszc.matches(NUMBER_REG);
    }
    private static String baseCode = "0123456789ABCDEFGHJKLMNPQRTUWXY";
    private static final String BASE_CODE_REGEX = "[" + baseCode + "]{18}";
    private static char[] baseCodeArray = baseCode.toCharArray();
    private static int[] wi = {1, 3, 9, 27, 19, 26, 16, 17, 20, 29, 25, 13, 8, 24, 10, 30, 28};

    /**
     * 生成供较验使用的 Code Map
     *
     * @return BidiMap
     */
    static BidiMap<Character, Integer> generateCodes() {
        BidiMap<Character, Integer> codes = new TreeBidiMap<>();
        for (int i = 0; i < baseCode.length(); i++) {
            codes.put(baseCodeArray[i], i);
        }

        return codes;
    }

    /**
     * 较验社会统一信用代码
     *
     * @param unifiedCreditCode 统一社会信息代码
     * @return 符合: true
     */
    public static boolean validateUnifiedCreditCode(String unifiedCreditCode) {
        if ((unifiedCreditCode.equals("")) || unifiedCreditCode.length() != 18 || !Pattern.matches(BASE_CODE_REGEX, unifiedCreditCode)) {
            return false;
        }

        Map<Character, Integer> codes = generateCodes();
        int parityBit;
        try {
            parityBit = getParityBit(unifiedCreditCode, codes);
        } catch (ValidationException e) {
            return false;
        }

        return parityBit == codes.get(unifiedCreditCode.charAt(unifiedCreditCode.length() - 1));
    }

    /**
     * 获取较验码
     *
     * @param unifiedCreditCode 统一社会信息代码
     * @param codes             带有映射关系的国家代码
     * @return 获取较验位的值
     */
    static int getParityBit(String unifiedCreditCode, Map<Character, Integer> codes) {
        char[] businessCodeArray = unifiedCreditCode.toCharArray();

        int sum = 0;
        for (int i = 0; i < 17; i++) {
            char key = businessCodeArray[i];
            if (baseCode.indexOf(key) == -1) {
                throw new ValidationException();
            }
            sum += (codes.get(key) * wi[i]);
        }
        int result = 31 - sum % 31;
        return result == 31 ? 0 : result;
    }

    public static boolean isRightSerialnumber(String shxym) {
        try {
            return validateUnifiedCreditCode(shxym);
        } catch (Exception e) {
            return false;
        }
    }

    public static List<String> removeDuplicate(List<String> list) {
        HashSet h = new HashSet(list);
        list.clear();
        list.addAll(h);
        return list;
    }

    public static void main(String[] args) {
        System.out.println(SerialnumberUtil.isRightSerialnumber("31370000MD0206524F"));
    }
}
